package jp.co.toshiba.ffsa.service.csas;

import java.sql.Timestamp;
import java.util.Calendar;

import jp.co.toshiba.ffsa.common.MakeHash;
import jp.co.toshiba.ffsa.common.Validation;
import jp.co.toshiba.ffsa.entity.User;
import jp.co.toshiba.ffsa.mail.SendMaiMail;
import jp.co.toshiba.ffsa.service.common.ConstantValue;

import org.seasar.extension.jdbc.JdbcManager;
import org.seasar.extension.jdbc.where.ComplexWhere;
import org.seasar.extension.jdbc.where.SimpleWhere;
import org.seasar.framework.container.SingletonS2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import org.seasar.mai.mail.MailAddress;
import org.seasar.struts.util.MessageResourcesUtil;

import com.ozacc.mail.MailSendException;

/**
 * (パスワード変更警告)パスワード変更入力
 * @author npc
 */
public class Csas402Service {
    /** パスワードチェックのエラーコード */
    private String errorCode          = "";
    /** ユーザーID */
    private String userID             = "";
    /** 現パスワード */
    private String currentPassword    = "";
    /** 新パスワード */
    private String newPassword        = "";
    /** 旧パスワードのユーザーマスタ */
    private User user = null;

    /**
     * パスワード変更処理
     * @return
     */
    public boolean savePassword() throws Exception{
        try{
            // パスワードの入力チェック
            if(this.checkInputPassword()){
                // チェックが通れば登録を行う
                this.entryNewPassword();
                // メール送信処理
                this.mailSend();
                return true;
            }else{
                return false;
            }
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * 旧、新パスワードの入力チェックを行う
     * @return
     * @throws Exception
     */
    private boolean checkInputPassword() throws Exception{
        try{
            if(!this.getUserPassword(false)){
                // 旧パスワードで検索できなかった場合
                this.errorCode = "errors.password";
                return false;
            }
            if(!this.getUserPassword(true)){
                // 新パスワードで履歴を含め検索できた場合
                this.errorCode = "errors.password_history";
                return false;
            }
            if(!this.passwordCheck()){
                // 数字だけか英字だけの場合
                this.errorCode = "errors.password_both_letter";
                return false;
            }
            if(!this.pwdEaCheck()){
                // の場合
                this.errorCode = "errors.password_duplicate_id";
                return false;
            }
       }catch(Exception e){
            throw e;
        }
        return true;
    }

    /**
     * パスワードのチェック処理
     * 英字だけと数字だけの場合NG
     * @throws Exception
     */
    public boolean passwordCheck() throws Exception{

        try{
            //パスワードが半角数字のみの場合または半角アルファベットのみの場合
            if(newPassword.matches("^[0-9]+$")){return false;}
            if(newPassword.matches("^[a-z]+$")){return false;}
            if(newPassword.matches("^[A-Z]+$")){return false;}
        }catch(Exception e){
            throw e;
        }
        return true;
    }
    /**
     * パスワードのチェック処理
     * メールアドレスを含むのはNG
     * @throws Exception
     */
    public boolean pwdEaCheck() throws Exception{
        boolean passwordCheck;
        try{
            //パスワードと同じ文字がメールアドレスに含れるかチェック
            Validation validation = new Validation();
            String emailAddress = getUser();

            passwordCheck = validation.passwordCheck(emailAddress, newPassword);
        }catch(Exception e){
            throw e;
        }
        return passwordCheck;
    }

    /**
     * 旧または新パスワードを取得する
     * @param newPasswordSearch
     * @return
     * @throws Exception
     */
    private boolean getUserPassword(boolean newPasswordSearch) throws Exception{
        // S2Container初期化
        SingletonS2ContainerFactory.init();
        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{
            // 検索条件
            SimpleWhere swh = new SimpleWhere().eq("userID", this.userID)
                                               .eq("deleteFlag", "0");

            ComplexWhere cwh = null;
            if(newPasswordSearch){
                // 新パスワード
                cwh = new ComplexWhere().eq("password", MakeHash.getSha256HashCode(this.newPassword))
                                        .or()
                                        .eq("passwordHistroty1", MakeHash.getSha256HashCode(this.newPassword))
                                        .or()
                                        .eq("passwordHistroty2", MakeHash.getSha256HashCode(this.newPassword))
                                        .or()
                                        .eq("passwordHistroty3", MakeHash.getSha256HashCode(this.newPassword))
                                        ;
            }else{
                // 旧パスワード
                cwh = new ComplexWhere().eq("password",MakeHash.getSha256HashCode(this.currentPassword));
            }

            // 一覧取得
            User user = jdbcManager.from(User.class)
                                   .where(swh, cwh)
                                   .getSingleResult()
                                   ;
            if(user == null && newPasswordSearch){
                // 新パスワードの条件で検索できなければok
                return true;
            }else if(user != null && !newPasswordSearch){
                // 旧パスワードの条件で検索できればok
                this.user = user;
                return true;
            }else{
                // 新パスワードの条件で検索できた場合、旧パスワードの条件で検索できなかった場合はng
                return false;
            }
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * 新パスワードの更新を行う
     * @throws Exception
     */
    private void entryNewPassword() throws Exception{
        // S2Container初期化
        SingletonS2ContainerFactory.init();
        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{
            // 当日取得
            Calendar cal = Calendar.getInstance();
            // プロパティの値を変更
            user.passwordHistroty3 = user.passwordHistroty2;
            user.passwordHistroty2 = user.passwordHistroty1;
            user.passwordHistroty1 = user.password;
            user.password          = MakeHash.getSha256HashCode(this.newPassword);
            user.passwordUpdateAt  = new Timestamp(cal.getTime().getTime());
            user.updatedAt         = new Timestamp(cal.getTime().getTime());
            user.updatedBy         = user.userID;
            // 更新
            jdbcManager.update(user).includes("password"
                                             ,"passwordHistroty1"
                                             ,"passwordHistroty2"
                                             ,"passwordHistroty3"
                                             ,"passwordUpdateAt"
                                             ,"updatedAt"
                                             ,"updatedBy"
                                             ).execute()
                                             ;
            return;
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * メール送信処理
     * @return 処理結果
     * @throws Exception エラー
     */
    public void mailSend( ) throws Exception {
        boolean successFlag = false;
        try {

            // メール情報をセット
            SendMaiMail sendMaiMail = new SendMaiMail();

            // 送信元メールアドレス(From)
            String mailAddressFrom = MessageResourcesUtil.getMessage("mail_address_from");
            sendMaiMail.setMailAddressFrom(mailAddressFrom);

            // 送信先メールアドレス(To)
            String emailAddress = "";
            
            emailAddress = getUser();
            
            MailAddress[] sendMailAddressTo = new MailAddress[1];
            sendMailAddressTo[0] = new MailAddress(emailAddress,"");

            sendMaiMail.setMailAddressTo(sendMailAddressTo);

            sendMaiMail.setReplacementSubject("");
            // 送信
            successFlag = sendMaiMail.sendMail(ConstantValue.pwdUpdMail);

            if(!successFlag){
                this.errorCode = "csas503.902";
            }

        }catch(MailSendException m){
        }catch(Exception e){
            e.printStackTrace();
            throw e;
        }

    }

    /**
     * ユーザーメールアドレス取得処理
     * @throws Exception
     */
    public String getUser() throws Exception{
    	
    	String emailAddress = "";
        // S2Container初期化
        SingletonS2ContainerFactory.init();

        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{
            // 検索条件
            SimpleWhere swh = new SimpleWhere().eq("userID", this.userID)
                                               .eq("deleteFlag", "0");

            // 一覧取得
            User user= jdbcManager.from(User.class)
                                     .where(swh)
                                     .getSingleResult()
                                     ;
            if(user != null){
            	emailAddress = user.mailAddress;
            }

        }catch(Exception e){
            throw e;
        }
        
        return emailAddress;
    }

    /**
     * ユーザーIDをセットする
     * @param userID
     */
    public void setUserID(String userID){this.userID = userID;}
    /**
     * 現パスワードをセットする
     * @param currentPassword
     */
    public void setCurrentPassword(String currentPassword){this.currentPassword = currentPassword;}
    /**
     * 新パスワードをセットする
     * @param newPassword
     */
    public void setNewPassword(String newPassword){this.newPassword = newPassword;}
    /**
     * 入力チェックエラーコードを取得する
     * @return errorCode
     */
    public String getErrorCode(){return this.errorCode;}
}
